package com.zuozhj.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.zuozhj.security.CaptchaFilter;
import com.zuozhj.security.JwtAccessDeniedHandler;
import com.zuozhj.security.JwtAuthenticationEntryPoint;
import com.zuozhj.security.JwtAuthenticationFilter;
import com.zuozhj.security.JwtLogoutSuccessHandler;
import com.zuozhj.security.LoginFailureHandler;
import com.zuozhj.security.LoginSuccessHandler;
import com.zuozhj.security.UserDetailServiceImpl;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    @Autowired
    LoginFailureHandler loginFailureHandler;

    @Autowired
    LoginSuccessHandler loginSuccessHandler;

    @Autowired
    JwtLogoutSuccessHandler jwtLogoutSuccessHandler;

    @Autowired
    CaptchaFilter captchaFilter;

    @Autowired
    JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    JwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Autowired
    UserDetailServiceImpl userDetailServiceImpl;
    
    @Autowired
    private AuthenticationConfiguration auth;

    /**
     * 编写AuthenticationManager的bean
     */
    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return auth.getAuthenticationManager();
    }

    @Bean
    JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
        JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(authenticationManager());
        return jwtAuthenticationFilter;
    } 

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //配置接口与加密方式
        auth.userDetailsService(userDetailServiceImpl).passwordEncoder(passwordEncoder());
    }

    /* 不需要登录访问的白名单 */
    private final static String[] URL_WHITELIST = {
        "/login",
        "/logout",
        "/captcha",
        "/test",
        "/test/*",
        "/test.html",
        "/favicon.ico"
    };

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 前后端分离后不需要用表单令牌
        // http.cors().and().csrf().disable()
        //     .formLogin()
        //         .successHandler(loginSuccessHandler)
        //         .failureHandler(loginFailureHandler)
        //         // .defaultSuccessUrl("/test")
        //     // 重写登出
        //     .and()
        //         .logout()
        //         .logoutSuccessHandler(jwtLogoutSuccessHandler)
            
        //     .and()
        //     // 使用redis存储缓存数据, 禁用session
        //         .sessionManagement()
        //         .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        //     .and()
        //         .authorizeRequests()
        //         .antMatchers(URL_WHITELIST).permitAll()
        //         .anyRequest().authenticated()
        //     .and()
        //         .exceptionHandling()
        //         .authenticationEntryPoint(jwtAuthenticationEntryPoint)
        //         .accessDeniedHandler(jwtAccessDeniedHandler)
        //     // 自定义过滤器, 校验验证码在校验账号密码之前>..
        //     .and()
        //         .addFilter(jwtAuthenticationFilter())
        //         .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
        //     ;
            http.cors(withDefaults()).csrf(request -> request.disable())
                .formLogin(login -> login
                        .successHandler(loginSuccessHandler)
                        .failureHandler(loginFailureHandler)
                        // .defaultSuccessUrl("/test")
                        )
                .logout(requests -> requests.logoutSuccessHandler(jwtLogoutSuccessHandler))
                // .logout(withDefaults())
                // 使用redis存储缓存数据, 禁用session
                .sessionManagement(requests -> requests.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(requests -> requests
                        .antMatchers(URL_WHITELIST).permitAll()
                        .anyRequest().authenticated())
                .exceptionHandling(withDefaults())
                .addFilter(jwtAuthenticationFilter())
                .addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class)
            ;
        return http.build();
    }
}
